﻿#ifndef _VARIANT_H
#define _VARIANT_H
#ifdef __cplusplus
extern "C"
{
#endif

//ALGORITH

#include "data_struct.h"

// 数据的释放函数
typedef int (*VARIANT_RELEASE_FN)(void*);
typedef int (*VARIANT_ADDREF_FN)(void*);
// 计算结果
struct variant_s {
    int                 type;               // 类型
    union {                                 // 值
        double          d;
        int             i;
        void            *ptr;               // 指针
        void            **pptr;             // 二级指针
    } u;
//    int                 ref_count;          // 指针引用计数
    VARIANT_ADDREF_FN   fn_addref;
    VARIANT_RELEASE_FN  fn_release;
};

// 实例对象
#define INIT_VARIANTOBJ(s)                      memset(&(s), 0, sizeof(s))
#define SET_VARIANTOBJ_TO_STRING(s, _ptr)       (s).type=VALUETYPE_STRING; (s).u.ptr=_ptr
#define SET_VARIANTOBJ_TO_DOUBLE(s, _d)       (s).type=VALUETYPE_DOUBLE; (s).u.d=_d
#define SET_VARIANTOBJ_TO_INT(s, _i)          (s).type=VALUETYPE_INTEGER; (s).u.i=_i
#define SET_VARIANTOBJ_TO_PTR(s, _ptr,_t)     (s).type=_t; (s).u.ptr=_ptr
#define SET_VARIANTOBJ_TO_PPTR(s, _pptr,_t)   (s).type=_t; (s).u.pptr=_pptr
#define SET_VARIANTOBJ_FN(s, addref, release)  (s).fn_addref = addref;(s).fn_release = release

#define VARIANTOBJ_TYPE(s)                    (s).type
#define VARIANTOBJ_STRING(s)                  (struct astring_s*)(s).u.ptr
#define VARIANTOBJ_DOUBLE(s)                  (s).u.d
#define VARIANTOBJ_INT(s)                     (s).u.i
#define VARIANTOBJ_PTR(s)                     (s).u.ptr
#define VARIANTOBJ_PPTR(s)                    (s).u.pptr

#define VARIANTOBJ_IS_TYPE(s,t)               (t==VARIANTOBJ_TYPE(s))
#define VARIANTOBJ_IS_ARRAY(s)                ((s).type & VALUETYPE_ARRAY)
#define VARIANTOBJ_IS_PTR(s)                  ((s).type & VALUETYPE_PTR)
#define VARIANTOBJ_IS_STRING(s)               (VALUETYPE_STRING==(s).type)
#define VARIANTOBJ_IS_COMOBJ(s)               (VARIANTOBJ_IS_STRING(s) || VARIANTOBJ_IS_ARRAY(s) || VARIANTOBJ_IS_PTR(s) )

// 指针对象
#define INIT_VARIANTPTR(s)                    memset((s), 0, sizeof(*(s)))
#define SET_VARIANTPTR_TO_STRING(s, _ptr)     (s)->type=VALUETYPE_STRING; (s)->u.ptr=_ptr
#define SET_VARIANTPTR_TO_DOUBLE(s, _d)       (s)->type=VALUETYPE_DOUBLE; (s)->u.d=_d
#define SET_VARIANTPTR_TO_INT(s, _i)          (s)->type=VALUETYPE_INTEGER; (s)->u.i=_i
#define SET_VARIANTPTR_TO_PTR(s, _ptr,_t)     (s)->type=_t; (s)->u.ptr=_ptr
#define SET_VARIANTPTR_TO_PPTR(s, _pptr,_t)   (s)->type=_t; (s)->u.pptr=_pptr
//#define SET_VARIANTPTR_FREE_FN(s, fn)           (s)->free_fn = fn;
#define SET_VARIANTPTR_FN(s, addref, release)  (s)->fn_addref = addref;(s)->fn_release = release

#define VARIANTPTR_TYPE(s)                    (s)->type
#define VARIANTPTR_STRING(s)                  (struct astring_s*)(s)->u.ptr
#define VARIANTPTR_DOUBLE(s)                  (s)->u.d
#define VARIANTPTR_INT(s)                     (s)->u.i
#define VARIANTPTR_PTR(s)                     (s)->u.ptr
#define VARIANTPTR_PPTR(s)                    (s)->u.pptr

#define VARIANTPTR_IS_TYPE(s,t)               (t==VARIANTPTR_TYPE(s))
#define VARIANTPTR_IS_ARRAY(s)                ((s)->type & VALUETYPE_ARRAY)
#define VARIANTPTR_IS_PTR(s)                  ((s)->type & VALUETYPE_PTR)
#define VARIANTPTR_IS_STRING(s)               (VALUETYPE_STRING==(s)->type)
#define VARIANTPTR_IS_COMOBJ(s)               (VARIANTPTR_IS_STRING(s) || VARIANTPTR_IS_ARRAY(s) || VARIANTPTR_IS_PTR(s) )
#define VARIANTPTR_IS_SAME(s, d)              (0==memcmp(s, d, sizeof(struct variant_s)))

// 变量声明
#define DECLARE_VARIANTOBJ(var)               struct variant_s var={0}
//#define DECLARE_STRING_VARIANTOBJ(var, ptr)   struct variant_s var={0}; SET_VARIANTOBJ_TO_STRING(var,ptr)
#define DECLARE_DOUBLE_VARIANTOBJ(var, d)     struct variant_s var={0}; SET_VARIANTOBJ_TO_DOUBLE(var,d)
#define DECLARE_INT_VARIANTOBJ(var, d)        struct variant_s var={0}; SET_VARIANTOBJ_TO_INT(var,d)
#define DECLARE_PTR_VARIANTOBJ(var, d, t)     struct variant_s var={0}; SET_VARIANTOBJ_TO_PTR(var,d,t)
#define DECLARE_PPTR_VARIANTOBJ(var, d, t)    struct variant_s var={0}; SET_VARIANTOBJ_TO_PPTR(var,d,t)


extern struct variant_s null_variant;

// 清理变体，主要对字符串
int variant_addref(struct variant_s*);
int variant_release(struct variant_s*);
void variant_reset(struct variant_s*);
int  variant_is_true(struct variant_s*);

int variant_init_astring(struct variant_s*, const char*);
void variant_clear_astring(struct variant_s*);

#ifdef __cplusplus
}
#endif
#endif
